package com.gitee.wsl.compose.chart.sleepgraph

import androidx.compose.animation.core.Spring
import androidx.compose.animation.core.Transition
import androidx.compose.animation.core.animateDp
import androidx.compose.animation.core.animateFloat
import androidx.compose.animation.core.spring
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.drawWithCache
import androidx.compose.ui.geometry.CornerRadius
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.geometry.Rect
import androidx.compose.ui.geometry.RoundRect
import androidx.compose.ui.geometry.Size
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.Path
import androidx.compose.ui.graphics.StrokeCap
import androidx.compose.ui.graphics.StrokeJoin
import androidx.compose.ui.graphics.drawscope.Stroke
import androidx.compose.ui.graphics.drawscope.clipPath
import androidx.compose.ui.unit.dp
import androidx.compose.ui.util.lerp
import com.gitee.wsl.compose.chart.sleepgraph.bean.SleepDayData
import com.gitee.wsl.compose.chart.sleepgraph.bean.SleepType
import com.gitee.wsl.time.between
import kotlin.time.Duration

//链接：https://juejin.cn/post/7449649677266894898

private const val animationDuration = 500
private val barHeight = 24.dp //每个睡眠阶段矩形的高度

val SleepAwake = Color(0xFFFFEAC1) // 清醒时期
val SleepRem = Color(0xFFFFDD9A) // 快速动眼睡眠
val SleepLight = Color(0xFFFFCB66) // 核心睡眠
val SleepDeep = Color(0xFFFF973C) // 深度睡眠


@Composable
fun SleepRoundedBar(
    sleepDayData: SleepDayData,
    transition: Transition<Boolean>
) {
    val animateHeight by transition.animateDp(
        label = "height",
        transitionSpec = {
            spring(
                dampingRatio = Spring.DampingRatioLowBouncy,
                stiffness = Spring.StiffnessLow
            )
        }
    ) { isExpanded ->
        if (isExpanded) 100.dp else 24.dp
    }

    val animationProgress by transition.animateFloat(
        label = "progress",
        transitionSpec = {
            spring(
                dampingRatio = Spring.DampingRatioLowBouncy,
                stiffness = Spring.StiffnessLow
            )
        }) { isExpanded ->
        if (isExpanded) 1f else 0f
    }

    Spacer(modifier = Modifier
        .drawWithCache {
            val barHeightPx = barHeight.toPx()
            val sleepGraphPath = Path()
            val stroke = Stroke(
                width = 2.dp.toPx(),
                cap = StrokeCap.Round,
                join = StrokeJoin.Round
            )
            val sleepGradientBarColorStops = arrayOf(
                0f to SleepAwake,
                0.33f to SleepRem,
                0.66f to SleepLight,
                1f to SleepDeep
            )
            val gradientBrush = Brush.verticalGradient(
                colorStops = sleepGradientBarColorStops,
                startY = 0f,
                endY = SleepType.entries.size * barHeightPx
            )

            sleepDayData.sleepPeriods.forEach { period ->
                // 添加代表每个睡眠阶段的矩形
                val percentageOfTotal = period.duration
                    .toMinutes()
                    .toFloat() / sleepDayData.totalTimeInBed
                    .toMinutes()
                    .toFloat()
                val periodWidth = percentageOfTotal * this.size.width

                // 计算初始坐标
                val offsetStartX =
                    Duration
                        .between(sleepDayData.firstSleepStart, period.startTime)
                        .toMinutes()
                        .toFloat() /
                            sleepDayData.totalTimeInBed
                                .toMinutes()
                                .toFloat() *
                            this.size.width
                val heightBySleepType = when (period.type) {
                    SleepType.Awake -> 0f
                    SleepType.REM -> barHeightPx
                    SleepType.Light -> barHeightPx * 2
                    SleepType.Deep -> barHeightPx * 3
                }
                val offsetStartY = lerp(
                    0f,
                    heightBySleepType,
                    animationProgress
                )

                sleepGraphPath.lineTo(offsetStartX, offsetStartY + barHeightPx / 2)
                sleepGraphPath.addRect(
                    Rect(
                        offset = Offset(offsetStartX, offsetStartY),
                        size = Size(periodWidth, barHeightPx)
                    )
                )
                sleepGraphPath.moveTo(
                    offsetStartX + periodWidth,
                    offsetStartY + barHeightPx / 2
                )
            }
            val animateCornerRadius = CornerRadius(
                lerp(
                    10.dp.toPx(),
                    2.dp.toPx(),
                    animationProgress
                )
            )
            val roundCornerPath = Path()
            roundCornerPath.addRoundRect(
                RoundRect(
                    Rect(
                        Offset(0f, 0f),
                        Size(this.size.width, this.size.height)
                    ),
                    animateCornerRadius
                )
            )
            onDrawBehind {
                clipPath(roundCornerPath) {
                    drawPath(sleepGraphPath, gradientBrush)
                    drawPath(sleepGraphPath, gradientBrush, style = stroke)
                }
            }
        }
        .height(animateHeight)
        .fillMaxWidth()
    )
}

private fun Duration.toMinutes() = this.inWholeMinutes
